define [
  'handlebars'
  'chaplin'
  'lib/utils'
], (Handlebars, Chaplin, utils) ->

  'use strict'

  # Form Helpers
  # =============================================================

  formatOptions = (options) ->
    defaults = label: 'Label'

    _.defaults options, defaults

    attrs          = []
    labelAttrs     = []
    formGroupClass = 'form-group'

    if options.className
      options.className += ' form-control'
    else
      options.className = 'form-control'
    attrs.push "class=\"#{options.className}\""
    delete options.className

    unless options.required
      delete options.required
    else
      options.label += "<em>*</em>"

    if options.labelClass
      labelAttrs.push "class=\"control-label #{options.labelClass}\""
      delete options.labelClass
    else
      labelAttrs.push 'class="control-label"'

    if options.id?
      attrs.push "id=\"#{options.id}\""
      labelAttrs.push "for=\"#{options.id}\""
      delete options.id

    formGroupClass += " #{options.formGroupClass}" if options.formGroupClass

    for key, value of options
      attrs.push "#{key}=\"#{value}\""

    delete attrs.label

    return [attrs, labelAttrs, formGroupClass]

  formatPrefixAndSuffix = (options, input) ->
    str = ""
    if options.prefix? and options.suffix?
      str += """
        <div class="input-prepend input-append">
          <span class="add-on">#{options.prefix}</span>#{input}<span class="add-on">#{options.suffix}</span>
        </div>
      """
    else if options.prefix?
      str += """
        <div class="input-prepend">
          <span class="add-on">#{options.prefix}</span>#{input}
        </div>
      """
    else if options.suffix?
      str += """
        <div class="input-append">
          #{input}<span class="add-on">#{options.suffix}</span>
        </div>
      """
    else
      str += """
        #{input}
      """

    return str

  # Select Input
  # =============================================================

  #---------------------- Imput ----------------------#
  Handlebars.registerHelper 'input', (options) ->
    [attrs, labelAttrs, formGroupClass] = formatOptions options.hash

    value = if options.fn? then options.fn(this) else ''

    str = """
    <div class="#{formGroupClass}">
      <label #{labelAttrs.join(' ')}>#{options.hash.label}</label>
    """

    str += formatPrefixAndSuffix options.hash, "<input #{attrs.join(' ')} />"

    str += """
      #{$.trim(value)}
    </div>
    """

    new Handlebars.SafeString str

  Handlebars.registerHelper 'textareaInput', (options) ->
    [attrs, labelAttrs, formGroupClass] = formatOptions options.hash

    value = if options.fn? then options.fn(this) else ''

    str = """
    <div class="#{formGroupClass}">
      <label #{labelAttrs.join(' ')}>#{options.hash.label}</label>
    """

    str += formatPrefixAndSuffix options.hash, "<textarea #{attrs.join(' ')}></textarea>"

    str += """
      #{$.trim(value)}
    </div>
    """

    new Handlebars.SafeString str

  #---------------------- Select input ----------------------#
  Handlebars.registerHelper 'selectInput', (context, options) ->
    if options.hash?.empty?
      empty = options.hash?.empty
      delete options.hash.empty

    [attrs, labelAttrs, formGroupClass] = formatOptions options.hash

    body = if options.fn? then options.fn(this) else ''

    str = """
    <div class="#{formGroupClass}">
      <label #{labelAttrs.join(' ')}>#{options.hash.label}</label>
      <select #{attrs.join(' ')}>
    """
    if empty?
      str += "<option value=\"\">#{empty}</option>"

    if context?
      createItem = (key, label) ->
        if _.isObject label
          o = label
          for k, l of o
            key = k
            label = l

        return '<option value="' + key + '">' + label + '</option>'

      if _.isArray context
        for label, key in context then str += createItem key, label
      else if _.isObject context
        for key, label of context then str += createItem key, label

    str += """
      </select>
      #{body}
    </div>
    """

    new Handlebars.SafeString str

  #---------------------- Checkbox group ----------------------#
  Handlebars.registerHelper 'checkboxGroup', (context, options) ->
    [attrs, labelAttrs, formGroupClass] = formatOptions options.hash

    body = if options.fn? then options.fn(this) else ''

    str = """
    <div class="#{formGroupClass}">
      <label #{labelAttrs.join(' ')}>#{options.hash.label}</label>
      <div class="form-control height-auto">
    """

    if context?
      createItem = (name='', key, label) ->
        if _.isObject label
          o = label
          for k, l of o
            key = k
            label = l
        """
          <div class="checkbox">
            <label>
              <input type="checkbox" value="#{key}" name="#{name}" />
              #{label}
            </label>
          </div>
        """

      if _.isArray context
        for label, key in context then str += createItem options.hash.name, key, label
      else if _.isObject context
        for key, label of context then str += createItem options.hash.name, key, label

    str += """
      #{body}
      </div>
    </div>
    """

    new Handlebars.SafeString str

  #---------------------- Radio group ----------------------#
  Handlebars.registerHelper 'radioGroup', (context, options) ->
    if options.hash.isInline
      isInline = true
      delete options.hash.isInline

    [attrs, labelAttrs, formGroupClass] = formatOptions options.hash

    body = if options.fn? then options.fn(this) else ''

    str = """
    <div class="#{formGroupClass}">
      <label #{labelAttrs.join(' ')}>#{options.hash.label}</label>
      #{if isInline then '<br />' else ''}
      <div class="form-control height-auto">
    """

    if context?
      createItem = (name='', key, label) ->
        if _.isObject label
          o = label
          for k, l of o
            key = k
            label = l
        strItem  = ''
        strItem += '<div class="radio">' unless isInline
        strItem += """
          <label #{if isInline then 'class="radio-inline"' else ''}>
            <input type="radio" value="#{key}" name="#{name}" />
            #{label}
          </label>
        """
        strItem += '</div>' unless isInline
        return strItem

      if _.isArray context
        for label, key in context then str += createItem options.hash.name, key, label
      else if _.isObject context
        for key, label of context then str += createItem options.hash.name, key, label

    str += """
        #{body}
      </div>
    </div>
    """

    new Handlebars.SafeString str

  #---------------------- Action buttons ----------------------#
  Handlebars.registerHelper 'buttons', (options) ->
    _.defaults options.hash, {
      submitLabel: 'Cadastrar'
      cancelLabel: 'Voltar'
    }

    formGroupClass = 'form-group'
    formGroupClass += " #{options.hash.formGroupClass}" if options.hash.formGroupClass

    str = "<div class=\"#{formGroupClass}\">"

    str += """
        <button type="submit" class="btn btn-primary pull-right">#{options.hash.submitLabel}</button>
    """

    if options.hash.cancelHref?
      str += """
        <a class="btn btn-default pull-right" #{' '}href="#{options.hash.cancelHref}" style="margin-right:5px;">#{options.hash.cancelLabel}</a>
      """

    str += """
      </div>
    """


    new Handlebars.SafeString str

  #---------------------- Form group ----------------------#
  Handlebars.registerHelper 'formGroup', (options) ->
    [attrs, labelAttrs, formGroupClass] = formatOptions options.hash

    body = if options.fn? then options.fn(this) else ''

    str = """
    <div class="#{formGroupClass}">
      <label #{labelAttrs.join(' ')}>#{options.hash.label}</label>
      #{body}
    </div>
    """

    new Handlebars.SafeString str

  null
